package cn.edu.scau.cmi.tangqingning.controll;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import cn.edu.scau.cmi.tangqingning.dao.impl.StudentDaoImpl;
import cn.edu.scau.cmi.tangqingning.dao.impl.UserDaoImpl;
import cn.edu.scau.cmi.tangqingning.model.Student;
import cn.edu.scau.cmi.tangqingning.model.User;
import cn.edu.scau.cmi.tangqingning.tools.StringUtil;

/**
 * 控制层-用户登录的逻辑处理<br>
 * 当客户使用get方式请求Servlet时，Web容器调用doGet方法处理请求，通过调用UserDaoImpl的isLogin方法或者StudentDaoImpl的isStuLogin方法登录
 * @author 唐庆宁
 *@see cn.edu.scau.cmi.tangqingning.dao.impl.UserDaoImpl#isLogin
 *@see cn.edu.scau.cmi.tangqingning.dao.impl.StudentDaoImpl#isStuLogin
 */
// HttpServlet容器响应Web客户请求流程如下：
// 1）Web客户向Servlet容器发出Http请求；
// 2）Servlet容器解析Web客户的Http请求；
// 3）Servlet容器创建一个HttpServletRequest对象(继承于ServletRequest)，在这个对象中封装Http请求信息；
// 4）Servlet容器创建一个HttpServletResponse对象；
// 5）Servlet容器调用HttpServlet的service方法，把HttpServletRequest和HttpServletResponse对象作为service方法的参数传给HttpServlet对象；
// 6）HttpServlet调用HttpServletRequest的有关方法，获取HTTP请求信息；
// 7）HttpServlet调用HttpServletResponse的有关方法，生成响应数据；
// 8）Servlet容器把HttpServlet的响应结果传给Web客户。
public class LoginServlet extends HttpServlet {

	/**
	 * 序列化版本号 定义一个静态常量来人为定义serialVersionUID 避免虚拟机默认计算serialVersionUID
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * @param request HttpServletRequest
	 * @param response HttpServletResponse
	 * @throws ServletException
	 * @throws IOException
	 */
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doPost(req, resp); // servlet碰到doGet方法调用直接就会去调用doPost方法
	}

	/**
	 * 重写doGet方法
	 * @param request HttpServletRequest
	 * @param response HttpServletResponse
	 * @throws ServletException
	 * @throws IOException
	 */
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("utf-8");// 解决乱码问题

		String indentity = req.getParameter("loginId");
		if (req.getParameter("username") != null) {
			String username = req.getParameter("username").trim();// 获取username并去掉空格
			String password = req.getParameter("password").trim();// 获取password并去掉空格
			String remember = req.getParameter("remember");

			req.setAttribute("username", username); // 将username这个对象保存在req作用域中，然后在转发进入的页面就可以获取到你的值
			req.setAttribute("password", password);
			// String sRand = (String) session.getAttribute("sRand"); 未知？？
			if (StringUtil.isEmpty(username) || StringUtil.isEmpty(password)) {// 判断账号密码是否为空
				req.setAttribute("error", "用户名或密码错误!");
				RequestDispatcher requestdispatcher = req.getRequestDispatcher("login.jsp");
				requestdispatcher.forward(req, resp); // 请求一次响应一次

			} else if ("userLogin".equals(indentity)) {// 非空，则创建用户对象
				// 如果是管理员身份处理代码
				User user = new User(username, password);
				UserDaoImpl usersdao = new UserDaoImpl();
				if (usersdao.isLogin(user)) {
					if ("remember-me".equals(remember)) { // 记住账号密码
						rememberMe(username, password, resp);
					}
					HttpSession session = req.getSession();
					session.setAttribute("username", username);
					RequestDispatcher requestdispatcher = req.getRequestDispatcher("userMain.jsp");// 将请求转发到userMain.jsp页面,request就是客户端的请求
					requestdispatcher.forward(req, resp); // 请求一次响应一次
					System.out.println(
							indentity + "：" + username + " 成功登录！       " + "IP：" + StringUtil.getRemortIP(req));
					bodyCounting(req); // 统计在线人数
					// System.out.println(indentity);
				} else {
					req.setAttribute("error", "用户名或密码错误!");
					RequestDispatcher requestdispatcher = req.getRequestDispatcher("login.jsp");
					requestdispatcher.forward(req, resp); // 请求一次响应一次
				}
			} else if ("studentLogin".equals(indentity)) {
				// 如果是学生身份
				Student student = new Student(Long.parseLong(username), Long.parseLong(password));
				StudentDaoImpl studentdao = new StudentDaoImpl();
				if (studentdao.isStuLogin(student)) {
					if ("remember-me".equals(remember)) { // 记住账号密码
						rememberMe(username, password, resp);
					}
					HttpSession session = req.getSession();
					session.setAttribute("username", username);
					RequestDispatcher requestdispatcher = req.getRequestDispatcher("studentMain.jsp");// 将请求转发到userMain.jsp页面,request就是客户端的请求
					requestdispatcher.forward(req, resp); // 请求一次响应一次
					System.out.println(
							indentity + "：" + username + " 成功登录！       " + "IP：" + StringUtil.getRemortIP(req));
					bodyCounting(req); // 统计在线人数
					// System.out.println(indentity);
				} else {
					req.setAttribute("error", "用户名或密码错误!");
					RequestDispatcher requestdispatcher = req.getRequestDispatcher("login.jsp");
					requestdispatcher.forward(req, resp); // 请求一次响应一次
				}
			}
		}
	}

	private void bodyCounting(HttpServletRequest req) {
		// TODO Auto-generated method stub
		System.out.println("<<<<_____创建session......");
		ServletContext context = req.getSession().getServletContext();
		Integer count = (Integer) context.getAttribute("count");
		if (count == null) {
			count = new Integer(1);
		} else {
			int co = count.intValue();
			count = new Integer(co + 1);
		}
		System.out.println("当前用户人数：" + count + "    " + new Date());
		context.setAttribute("count", count);// 保存人数
		// 计时器
		// StringUtil.timeTask(count);

	}

	private void rememberMe(String userName, String password, HttpServletResponse response) {
		Cookie user;
		try {
			user = new Cookie("user",
					URLEncoder.encode(userName, "UTF-8") + "-" + URLEncoder.encode(password, "UTF-8"));
			user.setMaxAge(1 * 60 * 60 * 24 * 7);
			response.addCookie(user);

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}
}
